package com.crm.aop;

import com.crm.annotation.LogOperation;
import com.crm.entity.Log;
import com.crm.mapper.LogMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class OperationLogAspect {

    @Autowired
    private LogMapper logMapper;

    @Around("@annotation(com.crm.annotation.LogOperation)")
    public Object around(ProceedingJoinPoint joinPoint){
        Log log = new Log();
        //获取请求方式
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String requestMethod = "";
        if (method.isAnnotationPresent(GetMapping.class)){
            requestMethod = "GET";
        }else if(method.isAnnotationPresent(PostMapping.class)) {
            requestMethod = "POST";
        }else if(method.isAnnotationPresent(PutMapping.class)){
            requestMethod = "PUT";
        }else if(method.isAnnotationPresent(DeleteMapping.class)){
            requestMethod = "DELETE";
        }
        //访问地址
        String request = request(joinPoint, method);
        //获取模块名称
        String title = method.getAnnotation(LogOperation.class).title();
        //获取登录ip
        String ip = getIpAddress();
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        //获取请求参数
        Map<String, Object> params = getMethodParams(joinPoint);
        //获取返回参数
        Object result = null;
        try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            //设置错误信息
            log.setErrorMsg(e.getMessage());
            log.setOperatorType(0);
            e.printStackTrace();
        }
        if(result != null){
            //设置返回参数
            log.setJsonResult(result.toString());
            log.setOperatorType(1);
        }
        log.setOperName("admin");
        log.setOperUrl(request);
        log.setOperParam(params.toString());
        log.setRequestMethod(requestMethod);
        log.setOperIp(ip);
        log.setTitle(title);
        log.setMethod(methodName);
        log.setOperTime(LocalDateTime.now());
        logMapper.insert(log);
        return result;
    }

    private Map<String, Object> getMethodParams(ProceedingJoinPoint joinPoint) {
        Map<String, Object> params = new HashMap<>();

        // 获取方法签名和参数名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String[] paramNames = ((LocalVariableTableParameterNameDiscoverer) new LocalVariableTableParameterNameDiscoverer()).getParameterNames(method);

        // 获取参数值
        Object[] args = joinPoint.getArgs();

        if (paramNames != null && args != null) {
            for (int i = 0; i < paramNames.length; i++) {
                String paramName = paramNames[i];
                Object paramValue = args[i];

                // 排除 HttpServletRequest、HttpServletResponse 等特殊类型
                if (!(paramValue instanceof HttpServletRequest) &&
                        !(paramValue instanceof HttpServletResponse)) {
                    params.put(paramName, paramValue);
                }
            }
        }
        return params;
    }

    //获取登录ip
    private String getIpAddress() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            return request.getRemoteAddr();
        }
        return "unknown";
    }
    //获取请求地址
    private  String request(ProceedingJoinPoint joinPoint, Method method) {
        // 获取访问地址
        Class<?> targetClass = joinPoint.getTarget().getClass();
        String classPath = "";
        if (targetClass.isAnnotationPresent(RequestMapping.class)) {
            RequestMapping annotation = targetClass.getAnnotation(RequestMapping.class);
            classPath = annotation.value().length > 0 ? annotation.value()[0] : "";
        }
        //获取路径地址
        String methodPath = "";
        if (method.isAnnotationPresent(RequestMapping.class)) {
            RequestMapping annotation = method.getAnnotation(RequestMapping.class);
            methodPath = annotation.value().length > 0 ? annotation.value()[0] : "";
        } else {
            if (method.isAnnotationPresent(GetMapping.class)) {
                methodPath = method.getAnnotation(GetMapping.class).value()[0];
            } else if (method.isAnnotationPresent(PostMapping.class)) {
                methodPath = method.getAnnotation(PostMapping.class).value()[0];
            } else if (method.isAnnotationPresent(PutMapping.class)) {
                methodPath = method.getAnnotation(PutMapping.class).value()[0];
            } else if (method.isAnnotationPresent(DeleteMapping.class)) {
                methodPath = method.getAnnotation(DeleteMapping.class).value()[0];
            }
        }
        //请求地址
        return classPath + methodPath;
    }
}
